package org.zju.demo.utils;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.context.ApplicationContext;

import java.io.Serializable;
import java.util.List;

/**
 * Created by admin on 2015/8/26.
 */
final public class HibernateUtil {
    private static SessionFactory sessionFactory = null;
    private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

    static {
        System.out.println("new sessionFactory");

        ApplicationContext ac = ApplicationContextUtil.getApplicationContext();
        sessionFactory = (SessionFactory) ac.getBean("sessionFactory");
    }

    private HibernateUtil(){

    }

    public static void setSessionFactory(SessionFactory factory) {
        sessionFactory = factory;
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static Session openSession() {
        return sessionFactory.openSession();
    }

    public static Session getCurrentSession() {
        Session session = threadLocal.get();

        if (session == null) {
            session = sessionFactory.openSession();
            threadLocal.set(session);
        }
        return session;
    }

    public static void colseCurrentSession() {
        Session session = getCurrentSession();

        if (session!= null && session.isOpen()) {
            session.close();
            threadLocal.set(null);
        }
    }

    public static Object getObjectById(Class clazz, Serializable id) {
        Session session = null;
        Object object = null;

        try{
            session = openSession();
            object = session.get(clazz, id);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
        return object;
    }

    public static void save(Object obj) {
        Session ss = null;
        Transaction tx = null;

        try{
            ss = openSession();
            tx = ss.beginTransaction();
            ss.save(obj);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            if (tx != null) {
                tx.rollback();
                throw new RuntimeException(e.getMessage());
            }
        } finally {
            if (ss != null && ss.isOpen()) {
                ss.close();
            }
        }
    }

    public static int saveIfNotExists(Object obj) {
        Session ss = null;
        Transaction tx = null;

        try{
            ss = openSession();
            tx = ss.beginTransaction();
            ss.save(obj);
            tx.commit();
        } catch (ConstraintViolationException e) {
            e.printStackTrace();
            if (tx != null) {
                tx.rollback();
            }
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            if (tx!=null) {
                tx.rollback();
            }
            throw new RuntimeException(e.getMessage());
        } finally {
            if (ss != null && ss.isOpen()) {
                ss.close();
            }
        }
        return 0;
    }

    public static void update(Object obj) {
        Session ss = null;
        Transaction tx = null;
        try {
            ss = openSession();
            tx = ss.beginTransaction();
            ss.update(obj);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            if (tx != null) {
                tx.rollback();
            }
            throw  new RuntimeException(e.getMessage());
        } finally {
            if (ss != null && ss.isOpen()) {
                ss.close();
            }
        }
    }
    public static void updateIfExists(Object obj) {
        Session ss = null;
        Transaction tx = null;

        try{
            ss = openSession();
            tx = ss.beginTransaction();
            ss.update(obj);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            if (tx != null) {
                tx.rollback();
            }
            throw new RuntimeException(e.getMessage());
        } finally {
            if (ss != null && ss.isOpen()) {
                ss.close();
            }
        }
    }

    public static void delete(Object obj) {
        Session ss = null;
        Transaction tx = null;

        try {
            ss = openSession();
            tx = ss.beginTransaction();
            ss.delete(obj);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            if (tx != null) {
                tx.rollback();
            }
            throw new RuntimeException(e.getMessage());
        } finally {
            if (ss != null && ss.isOpen()) {
                ss.close();
            }
        }
    }
    public static void saveOrUpdate(Object object) {
        Session ss = null;
        Transaction tx = null;

        try{
            ss = openSession();
            tx = ss.beginTransaction();
            ss.saveOrUpdate(object);
            tx.commit();
        }catch (Exception e) {
            e.printStackTrace();
            if (tx != null) {
                tx.rollback();;
            }
            throw new RuntimeException(e.getMessage());
        } finally {
            if (ss != null && ss.isOpen()) {
                ss.close();
            }
        }
    }

    public static List executeQuery(String hql, String[] parameters) {
        Session session = null;
        List list = null;

        try{
            session = openSession();
            Query query = session.createQuery(hql);

            if (parameters != null && parameters.length > 0) {
                for (int i = 0; i < parameters.length; ++ i) {
                    query.setString(i, parameters[i]);
                }
            }
            list = query.list();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } finally {
            if (session != null && session.isOpen()) {
                session.close();
            }
        }
        return list;
    }

    public static List executeQueryFinalNRecords(String hql, String[] parameters, Integer record_length) {
        Session session = null;
        List list = null;

        try{
            session = openSession();
            Query query = session.createQuery(hql);
            if (parameters!= null && parameters.length > 0) {
                for (int i = 0; i < parameters.length; ++ i) {
                    query.setString(i, parameters[i]);
                }
            }
            query.setMaxResults(record_length);
            list = query.list();
        } catch (Exception e) {
            e.printStackTrace();;
            throw new RuntimeException(e.getMessage());
        } finally {
            if (session!=null && session.isOpen()) {
                session.close();
            }
        }
        return list;
    }
    public static void executeUpdate(String hql, String[] parameters) {
        Session ss = null;
        Transaction tx = null;

        try{
            ss = openSession();
            tx = ss.beginTransaction();
            Query query = ss.createQuery(hql);

            if (parameters != null && parameters.length > 0) {
                for (int i = 0 ; i < parameters.length; ++ i) {
                    query.setString(i, parameters[i]);
                }
            }
            query.executeUpdate();
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            if (tx != null) {
                tx.rollback();
            }
            throw new RuntimeException(e.getMessage());
        } finally {
            if (ss != null && ss.isOpen()) {
                ss.close();
            }
        }
    }
    public static int executeUpdateIfExist(String hql, String[] parameters) {
        Session ss = null;
        Transaction tx = null;

        int updateNumbers = 0;

        try{
            ss = openSession();
            tx = ss.beginTransaction();

            Query query = ss.createQuery(hql);

            if (parameters!= null && parameters.length > 0) {
                for (int i = 0; i < parameters.length; ++ i) {
                    query.setString(i, parameters[i]);
                }
            }

            updateNumbers = query.executeUpdate();
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            if (tx != null) {
                tx.rollback();
            }
            throw new RuntimeException(e.getMessage());
        } finally {
            if (ss != null && ss.isOpen()) {
                ss.close();
            }
        }
        return updateNumbers;
    }
    public static Object objectQuery(String hql, String[] parameters) {
        Session ss = null;
        Object obj = null;
        Transaction tx = null;

        try{
            ss = openSession();
            tx = ss.beginTransaction();
            Query query = ss.createQuery(hql);

            if (parameters != null && parameters.length > 0) {
                for (int i = 0; i < parameters.length; ++ i) {
                    query.setString(i, parameters[i]);
                }
            }
            obj = query.uniqueResult();
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            if (tx!=null) {
                tx.rollback();
            }
            throw new RuntimeException(e.getMessage());
        } finally {
            if (ss != null && ss.isOpen()) {
                ss.close();
            }
        }
        return obj;
    }
}
